JULIA possède un système de type et de méthode qui lui confère une approche objet. La fonction typeof() renvoie le type d'une variable de base Int32, Float64... JULIA est conçu pour permettre facilement d'étendre l'environnement à de nouveaux type de variable.
Le types sont organisés suivant un hiérarchie comme on peut le voir sur l'arborescence partielle ci-dessous
(arborescence générée à l'aide de https://github.com/tanmaykm/julia_types/blob/master/julia_types.jl)
In [30]:
function f(x::Any)
sin(x+1)
end
Out[30]:
In [31]:
function f(n::Integer)
n
end
Out[31]:
In [32]:
f(3.0)
Out[32]:
In [33]:
f(3)
Out[33]:
In [34]:
f(im)
Out[34]:
In [35]:
f(-2)
Out[35]:
In [37]:
+
Out[37]:
In [38]:
+(1,2)
Out[38]:
In [15]:
f(sqrt(2))
In [58]:
abstract type Grid end # juste en dessous de Any
mutable struct Grid1d <: Grid
debut::Float64
fin::Float64
n::Int32
end
In [40]:
a=Grid1d(0,1,2)
Out[40]:
In [41]:
a.debut
Out[41]:
In [42]:
a.fin
Out[42]:
In [43]:
a.n
Out[43]:
In [44]:
function Base.show(io::IO,g::Grid1d)
print(io, "Grid 1d : début $(g.debut) , fin $(g.fin) , $(g.n) éléments\n")
end
In [45]:
Base.show(a)
In [47]:
println(a)
In [48]:
a
Out[48]:
In [55]:
import Base:+
function +(g::Grid1d,n::Integer)
g.n +=n
return g
end
Out[55]:
In [56]:
a=Grid1d(0,1,2)
Out[56]:
In [57]:
a+2
Out[57]:
In [60]:
a+=1
Out[60]:
Attention l'addition n'est pas forcément commutative !
In [61]:
2+a
ni unaire !
In [63]:
-a
Notez le message d'erreur qui est très claire !
In [64]:
a+[1,2]
In [65]:
function Base.size(g::Grid)
return g.n
end
In [66]:
size(a)
Out[66]:
In [67]:
function Base.det(g::Grid1d)
g.fin-g.debut
end
In [27]:
det(a)
Out[27]:
In [28]:
abstract Grid # juste en dessous de Any
type Grid1d <: Grid
debut::Float64
fin::Float64
n::Int32
# constructeurs par défaut sans argument
function Grid1d()
new(0,0,0)
end
# constructeurs par défaut avec argument
function Grid1d(a,b,c)
if c<=0
error("pas possible")
else
new(a,b,c)
end
end
end
In [29]:
b=Grid1d(0,1,-1)
Il devient possible de déterminer un constructeurs pour différentes entrées.
Il faut au préalable bien penser sa hiérarchie de type et écrire autant de fonctions constructeurs que de cas d'initialisation du nouveau type.
In [68]:
Base.start(a::Grid1d) = 1
function Base.next(a::Grid1d, state)
if state == 1
return (a.debut,2)
else
return (a.debut+(a.fin-a.debut)*(state-1)/a.n , state+1)
end
end
Base.done(a::Grid1d, state) = state > a.n +1
In [31]:
a=Grid1d(0,1,10)
Out[31]:
In [32]:
start(a)
Out[32]:
In [33]:
next(a,0)
Out[33]:
In [34]:
for i in a
println(i)
end
Il devient possible de construire des itérateurs sur une grille 2d, 3d renvoyant les coordonnées des points de la grille... Mais on peut imaginer sur une triangulation etc...